﻿using System;
using System.Linq;
using System.Threading.Tasks;
using VisionCloud.Domain.Common;
using VisionCloud.Utility.Redis;

namespace VisionCloud.Domain.Extension
{
    public class Contracts
    {
        /// <summary>
        /// 限定时间内限制请求次数
        /// </summary>
        /// <param name="key"></param>
        /// <param name="limit"></param>
        /// <param name="timeSpan"></param>
        /// <param name="exceptionMessage"></param>
        /// <returns></returns>
        public static async Task Frequency(string key, int limit, TimeSpan timeSpan, string exceptionMessage = "操作过于频繁", bool isMatch = true)
        {
            await Frequency<Exception>(key, limit, timeSpan, isMatch, exceptionMessage);
        }

        /// <summary>
        /// 限制请求次数
        /// </summary>
        /// <typeparam name="TException"></typeparam>
        /// <param name="key"></param>
        /// <param name="limit"></param>
        /// <param name="timeSpan"></param>
        /// <param name="exceptionMessage"></param>
        /// <returns></returns>
        public static async Task Frequency<TException>(string key, int limit, TimeSpan timeSpan, bool isMatch, string exceptionMessage = "操作过于频繁") where TException : Exception
        {
            var condition = isMatch ? await RedisHelper.Instance.GetAsync<int>(key) 
                : RedisHelper.Instance.GetKeys(key).ToList().Count;

            if (condition >= limit) throw new OperationException(exceptionMessage);
            else
            {
                await RedisHelper.Instance.SetAsync(key, ++condition, timeSpan);
            }
        }

        /// <summary>
        /// 检查key是否存在，若不存在则设置key
        /// </summary>
        /// <param name="key"></param>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        public static async ValueTask<bool> Exists(string key, TimeSpan timeSpan)
        {
            var existsKey = await RedisHelper.Instance.ExistsAsync(key);
            if (existsKey) return true;
            else
            {
                await RedisHelper.Instance.SetValueAsync(key, "", timeSpan);
            }
            return false;
        }
    }
}